﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
using TowerDefence_Zombie.Data;
using UnityGameFramework.Runtime;
using System;
using GameFramework.Fsm;
using GameFramework;
using Sirenix.OdinInspector;
using Assets.GameFramework.Scripts.Runtime.DailyTask;

namespace TowerDefence_Zombie
{
    public class EntityEnemy : EntityTargetable, IPause
    {
        public Animator animator;
        public float delayTiem;
        public SphereCollider targeterCollider;

        protected IFsm<EntityEnemy> fsm;
        protected List<FsmState<EntityEnemy>> stateList;

        [SerializeField,Title("死亡特效")] private GameObject deadEffect;

        private bool _slowDownState = false;
        private const float _slowDownDuration = 1.0f;
        private float _slowDownTimer = 0.0f;
        private float _curSlowRate = 1.0f;

        private bool _continuousDamageState = false;
        private const float _continuousDamageDuration = 1.0f;
        private float _continuousDamageTimer = 0.0f;
        private float _curContinuousDamage = 0.0f;
        private const float _continuousDamageIntetval = 0.3f;
        private float _continuousDamageIntervalTimer = 0.0f;

        /// <summary>
        /// 表示是否死亡或已攻击玩家即将回收，以防重复执行回收逻辑
        /// </summary>
        private bool hide = false;

        public override EnumAlignment Alignment
        {
            get
            {
                return EnumAlignment.Enemy;
            }
        }

        protected override float MaxHP
        {
            get
            {
                if (EntityDataEnemy != null)
                    return EntityDataEnemy.EnemyData.MaxHP;
                else return 0;
            }
        }

        public EntityDataEnemy EntityDataEnemy
        {
            get;
            private set;
        }

        public float CurrentSlowRate
        {
            get => _curSlowRate;
        }

        public NavMeshAgent Agent
        {
            get;
            private set;
        }

        public bool isPathBlocked
        {
            get { return Agent.pathStatus == NavMeshPathStatus.PathPartial; }
        }

        public bool isAtDestination
        {
            get { return Agent.remainingDistance <= Agent.stoppingDistance; }
        }

        public LevelPath LevelPath
        {
            get;
            private set;
        }

        public bool IsPause
        {
            get;
            private set;
        }

        public int CoinNum
        {
            get;
            private set;
        }

        protected override void OnInit(object userData)
        {
            base.OnInit(userData);

            Agent = GetComponent<NavMeshAgent>();
            hpBarRoot = transform.Find("HealthBar");
            stateList = new List<FsmState<EntityEnemy>>();
        }

        protected override void OnUpdate(float elapseSeconds, float realElapseSeconds)
        {
            base.OnUpdate(elapseSeconds, realElapseSeconds);
            if (IsPause) return;

            if (_slowDownState)
            {
                _slowDownTimer -= realElapseSeconds;
                if (_slowDownTimer <= 0)
                {
                    StopSlow();
                }
            }

            if (_continuousDamageState)
            {
                _continuousDamageTimer -= realElapseSeconds;
                if (_continuousDamageTimer <= 0)
                {
                    StopContinuousDamage();
                }
                else
                {
                    _continuousDamageIntervalTimer -= realElapseSeconds;
                    if (_continuousDamageIntervalTimer <= 0)
                    {
                        _continuousDamageIntervalTimer = _continuousDamageIntetval;
                        Damage(_curContinuousDamage,true);
                    }
                }
            }
        }

        protected override void OnShow(object userData)
        {
            base.OnShow(userData);

            EntityDataEnemy = userData as EntityDataEnemy;

            if (EntityDataEnemy == null)
            {
                Log.Error("Entity enemy '{0}' entity data invaild.", Id);
                return;
            }

            hide = false;
            Agent.enabled = true;
            LevelPath = EntityDataEnemy.LevelPath;
            hp = EntityDataEnemy.EnemyData.MaxHP;
            targeterCollider.radius = EntityDataEnemy.EnemyData.Range;
            targeterCollider.center = new(0, EntityDataEnemy.EnemyData.Range, 0);
            CoinNum = EntityDataEnemy.CoinNum;
            CreateFsm();

            GameEntry.Sound.PlaySound(EnumSound.ZombieSpawnMusic, null);
        }

        protected override void OnHide(bool isShutdown, object userData)
        {
            base.OnHide(isShutdown, userData);
            StopSlow();
            StopContinuousDamage();
            deadEffect.SetActive(false);
            LevelPath = null;
            EntityDataEnemy = null;
            hp = 0;
            Agent.enabled = false;
            hide = true;
            DestroyFsm();
        }

        protected virtual void AddFsmState()
        {
            stateList.Add(EnemyMoveState.Create());
            stateList.Add(EnemyDeadState.Create());
        }

        protected virtual void StartFsm()
        {
            fsm.Start<EnemyMoveState>();
        }

        private void CreateFsm()
        {
            AddFsmState();
            fsm = GameEntry.Fsm.CreateFsm(gameObject.name, this, stateList);
            StartFsm();
        }

        public override void Damage(float value, bool isPoison = false)
        {
            if (GameEntry.Data.GetData<DataPlayer>().GetPlayerData().PlayerSkillData.RemainDoubleAttackTime > 0)
            {
                value *= 2;
            }
            base.Damage(value);
            GameEntry.Event.Fire(this, ShowEntityBeDamageEventArgs.Create(1076, hpBarRoot.position, value, isPoison));
        }

        private void DestroyFsm()
        {
            GameEntry.Fsm.DestroyFsm(fsm);
            foreach (var item in stateList)
            {
                ReferencePool.Release((IReference)item);
            }
            stateList.Clear();
            fsm = null;
        }

        public void AfterAttack()
        {
            if (!hide)
            {
                hide = true;
                GameEntry.Event.Fire(this, HideEnemyEventArgs.Create(Id));
            }
        }

        protected override void Dead()
        {
            fsm.CurrentState.ChangeState<EnemyDeadState>(fsm);
            deadEffect.SetActive(false);
            deadEffect.SetActive(true);
            GameEntry.Sound.PlaySound(EnumSound.ZombieBombMusic, null);
            if (!isDeadState)
                isDeadState = true;
            if (CoinNum > 0)
            {
                if (GameEntry.Data.GetData<DataPlayer>().GetPlayerData().PlayerSkillData.DoubleGoldCount > 0)
                    CoinNum *= 2;
                GameEntry.Event.Fire(this, CreatCoinEventAgrs.Create(CoinNum, transform.position));
            }
            GameEntry.Event.Fire(this, TaskRunEventArgs.Create(1, 1));
        }

        public void DeadEvent()
        {
            base.Dead();
            if (!hide)
            {
                hide = true;
                GameEntry.Event.Fire(this, HideEnemyEventArgs.Create(Id));
            }
        }

        private void OnTriggerEnter(Collider other)
        {
            var player = other.GetComponent<EntityPlayer>();
            if (player == null)
            {
                return;
            }
            player.Damage(100);
        }

        public void ApplySlow(float slowRate)
        {
            if (IsDead || !Available) return;

            if (_slowDownState == false)
            {
                _slowDownState = true;
                _curSlowRate = slowRate;
                ChangeSlowFxState(true);
            }
            else if (_curSlowRate > slowRate)
            {
                _curSlowRate = slowRate;
            }
            _slowDownTimer = _slowDownDuration;
        }

        public void StopSlow()
        {
            _slowDownState = false;
            _curSlowRate = 1.0f;
            _slowDownTimer = 0.0f;
            ChangeSlowFxState(false);
        }

        private void ChangeSlowFxState(bool state)
        {
            //todo : 播放减速特效
        }

        public void ApplyContinuousDamage(float continuousDamage)
        {
            if (IsDead || !Available) return;

            if (_continuousDamageState == false)
            {
                _continuousDamageState = true;
                _curContinuousDamage = continuousDamage;
                _continuousDamageIntervalTimer = _continuousDamageIntetval;
                ChangeContinuousDamageFxState(true);
            }
            else if (_curContinuousDamage < continuousDamage)
            {
                _curContinuousDamage = continuousDamage;
            }
            _continuousDamageTimer = _continuousDamageDuration;
        }

        public void StopContinuousDamage()
        {
            _continuousDamageState = false;
            _curContinuousDamage = 0.0f;
            _continuousDamageTimer = 0.0f;
            _continuousDamageIntervalTimer = 0.0f;
            ChangeContinuousDamageFxState(false);
        }

        private void ChangeContinuousDamageFxState(bool state)
        {
            //todo : 播放灼烧特效
        }

        public void Pause()
        {
            IsPause = true;
            Agent.speed = 0;
        }

        public void Resume()
        {
            IsPause = false;
            Agent.speed = EntityDataEnemy.EnemyData.Speed * CurrentSlowRate;
        }
    }
}